package com.distributed.lock.config.impl;

import com.distributed.lock.utils.RedissonUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RLock;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * @program: SpringBootDemos
 * @description:
 * @author: Kangsen
 * @create: 2022-07-14 11:04
 **/
@Slf4j
@Component
@Configuration
@Aspect
public class EmLockAspect {

    @Resource
    private RedissonUtils redissonUtils;

    private final String UID_PREFIX = "tt-lock:";
    //进程ID
    private final String APPID = UidUtils.randomUID();
    //线程ID
    private final ThreadLocal<String> ThreadID = ThreadLocal.withInitial(UidUtils::randomUID);

    @Pointcut("@annotation(com.distributed.lock.config.impl.EmLock)")
    public void lockApp(){

    }

    @Around("lockApp()")
    public Object doAround(org.aspectj.lang.ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        //获取到环绕方法的注解
        EmLock emLock = method.getAnnotation(EmLock.class);
        if(emLock == null){
            //继续执行后续
            return point.proceed();
        }
        Object proceed = null;
        //LockRangeEnum lockRangeEnum = emLock.lockRange();
        //String uid =  lockRangeEnum == LockRangeEnum.APPLICATION ? APPID : ThreadID.get();
        RLock lock = null;
        if (emLock.executeMode().equals(LockExecuteMode.SKIPEXECUTION)) {
            //跳过执行模式  没拿到锁就不管了 不等待获取锁
            lock = redissonUtils.tryLockObj(UID_PREFIX + emLock.key() , emLock.waitTime(), emLock.timeout());
        }else{
            lock = redissonUtils.lock(UID_PREFIX  + emLock.key() , Long.valueOf(emLock.timeout()), emLock.timeunit());
        }
        if(lock != null){
            //拿到了锁 执行后续业务
            try {
                TimeUnit.MILLISECONDS.sleep(100);
                log.info("获取到锁");
                proceed = point.proceed();
            } catch (Exception e){
                e.printStackTrace();
                return point.proceed();
            } finally {
                log.info("执行完了  解锁");
                redissonUtils.unlock(lock);
            }
        }else{
            //没有拿到锁 就直接返回
            //return point.proceed();
            return null;
        }
        return proceed;
    }
}
